package main

import (
	"fmt"
	"net"
	"strings"
)

type User struct {
	Name string
	// ip地址
	Addr string
	// 用户channnel
	C    chan string
	// 当前用户的通讯链接
	conn net.Conn
	server *Server
}

// 创建一个用户的API
func NewUser(conn net.Conn,server *Server) *User{
	userAddr := conn.RemoteAddr().String()
	user := &User{
		Name: userAddr,
		Addr: userAddr,
		C: make(chan string),
		conn: conn,
		server: server,
	}
	// 启动监听
	go user.ListenMessage()

	return user
}

// 监听当前User channel的方法，一旦有消息
// 就直接发送给对端客户端
func (user *User) ListenMessage(){
	//当u.C通道关闭后，不再进行监听并写入信息
	for msg := range user.C {
		_, err := user.conn.Write([]byte(msg + "\n"))
		if err != nil {
		panic(err)
		  }
		 }
		//不监听后关闭conn，conn在这里关闭最合适
		 err := user.conn.Close()
		 if err != nil {
			panic(err)
		 }
}
// 用户的上线业务
func (u *User) Online(){
	//将用户加入到OnlineMap
	u.server.mapLock.Lock()
	u.server.OnlineMap[u.Name]= u
	u.server.mapLock.Unlock()
	// 广播用户上线的消息，
	u.server.BroadCast(u,"已上线")
}
// 用户的下线业务
func (u *User) Offline(){
u.server.mapLock.Lock()
delete(u.server.OnlineMap,u.Name)
u.server.mapLock.Unlock()

u.server.BroadCast(u,"已下线")
}
// 给当前user对应的客户端发消息
func (u *User) SendMsg(msg string){
    u.conn.Write([]byte(msg))
}
// 用户的处理消息
func (u *User) DoMessage(msg string){
	if msg=="who"{
		// 查询当前在线用户
		u.server.mapLock.Lock()
		for _,user := range u.server.OnlineMap{
            msg=fmt.Sprintf("【%v】%v:%v",user.Addr,user.Name,"在线...")
			u.SendMsg(msg+"\n")
		}
		u.server.mapLock.Unlock()
	}else if len(msg)>7 && msg[:7]=="rename|"{
       // 消息格式： rename|张三
       name := msg[7:]
	//    判断name是否存在
	// 这里有个小问题，就是应该在用户表里查
	// 而不是在在线用户表里查，这里就是个思路
	if _,ok := u.server.OnlineMap[name];ok{
		u.SendMsg("用户名已存在\n")
	}else{
		u.server.mapLock.Lock()
		// key是不可变类型的，只能删了重下
		delete(u.server.OnlineMap,u.Name)
		u.server.OnlineMap[name]=u
		u.server.mapLock.Unlock()
		u.Name=name
		u.SendMsg("您已更新用户名"+u.Name+"\n")
	}
	}else if len(msg)>4 && msg[:3]=="to|"{
		toName := strings.Split(msg,"|")[1]
		if toName==""{
			u.SendMsg("消息格式不正确，格式请参考 to|张三|你好啊\n")
			return
		}
		toMsg :=strings.Split(msg,"|")[2]
		if toMsg ==""{
			u.SendMsg("不能发送空消息\n")
			return
		}
		if user,ok := u.server.OnlineMap[toName];ok{
			Amsg:=fmt.Sprintf("【%v】%v对您说%v",u.Addr,u.Name,toMsg)
			user.SendMsg(Amsg)
			Amsg=fmt.Sprintf("您对%v说%v",user.Name,toMsg)
			u.SendMsg(Amsg)
		}else{
			u.SendMsg("用户名不存在\n")
			return
		}	
	}else{
		u.server.BroadCast(u,msg)
	}

}
// 内存会泄露吧，用户的conn还在另一个携程里面被占用
// 这是个评论，但咱也不懂这东西